#ifndef _OBJ_READER
#define _OBJ_READER


#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include "SampleUtils.h"
#include "vec.h"

#ifdef USE_OPENGL_ES_1_1
#include <GLES/gl.h>
#include <GLES/glext.h>
#else
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#endif

using namespace std;




class face{
public:
	/*face(vec3* vv1,vec3* vv2,vec3* vv3,vec2* tt1, vec2* tt2, vec2* tt3,vec3* nn1, vec3*nn2, vec3*nn3){
		v1=vv1;v2=vv2;v3=vv3;
		t1=tt1;t2=tt2;t3=tt3;
		n1=nn1;n2=nn2;n3=nn3;
	}*/

	face()
	{
	}
	
	void set(face *f){
		v1=f->v1;v2=f->v2;v3=f->v3;
		t1=f->t1;t2=f->t2;t3=f->t3;
		n1=f->n1;n2=f->n2;n3=f->n3;
	}
	/*vec3* v1;vec3* n1;vec2* t1;
	vec3* v2;vec3* n2;vec2* t2;
	vec3* v3;vec3* n3;vec2* t3;
*/
	int v1, v2,v3,t1,t2,t3,n1,n2,n3;
};

class obj3d{
private:
	
	int numFaces;
	
	
public:
	int numVerts;
	
	int numNormals;
	int numTexts;
	//int numIndices;
	face *faces;
	float *verts;
	float *norms;
	float *texts;
	//int *indices;
	
	obj3d(vector<face*> fs, vector<vec3*> vs, vector<vec2*>ts, vector <vec3*> ns)
	{
		numFaces=fs.size();
		
		numVerts=numFaces*3;
		numNormals=ns.size();
		numTexts=ts.size();
	//	numIndices=numFaces*3;
		
		verts=(float*)malloc(numFaces*3*3*sizeof(float));
		norms=(float*)malloc(numFaces*3*3*sizeof(float));
		texts=(float*)malloc(numFaces*2*3*sizeof(float));
		faces=(face*)malloc(numFaces*sizeof(face));
	//	indices=(int*)malloc(numFaces*3*sizeof(int));
		

		for (unsigned int i=0; i<fs.size();i++){faces[i].set(fs[i]);}
	/*	for (unsigned int i=0,j=0; i<vs.size()*3;j++,i+=3){
			vec3 v= *vs[j];
			verts[i]=v.x;verts[i+1]=v.y;verts[i+2]=v.z;
		}
		for (unsigned int i=0, j=0; i<ts.size()*2;i+=2){
			vec2 v= *ts[j];
			texts[i]=v.x;texts[i+1]=v.y;
		}
		for (unsigned int i=0, j=0; i<ns.size()*3;i+=3){
			vec3 v= *ns[j];
			norms[i]=v.x;norms[i+1]=v.y;norms[i+2]=v.z;
		}
*/
		for (unsigned int i=0,j=0,k=0; j<fs.size();j++,i+=9, k+=6){
			face fa=*fs[j];
			verts[i]=vs[fa.v1]->z;
			verts[i+1]=vs[fa.v1]->x;
			verts[i+2]=vs[fa.v1]->y;
			norms[i]=ns[fa.n1]->x;
			norms[i+1]=ns[fa.n1]->y;
			norms[i+2]=ns[fa.n1]->z;
			texts[k]=ts[fa.t1]->x;
			texts[k+1]=ts[fa.t1]->y;
					
			verts[i+3]=vs[fa.v2]->z;
			verts[i+4]=vs[fa.v2]->x;
			verts[i+5]=vs[fa.v2]->y;
			norms[i+3]=ns[fa.n2]->x;
			norms[i+4]=ns[fa.n2]->y;
			norms[i+5]=ns[fa.n2]->z;
			texts[k+2]=ts[fa.t2]->x;
			texts[k+3]=ts[fa.t2]->y;
					
			verts[i+6]=	vs[fa.v3]->z;
			verts[i+7]=vs[fa.v3]->x;
			verts[i+8]=vs[fa.v3]->y;
			norms[i+6]=ns[fa.n3]->x;
			norms[i+7]=ns[fa.n3]->y;
			norms[i+8]=ns[fa.n3]->z;
			texts[k+4]=ts[fa.t3]->x;
			texts[k+5]=ts[fa.t3]->y;
					


		}
		
		
	}

	
	face* getFaces(){return faces;}
	int getNumFaces(){return numFaces;};
	
	void draw(){
	
		
#ifdef USE_OPENGL_ES_1_1
	
        glTexCoordPointer(2, GL_FLOAT, 0, (const GLvoid*) texts);
        glVertexPointer(3, GL_FLOAT, 0, (const GLvoid*) verts);
        glNormalPointer(GL_FLOAT, 0,  (const GLvoid*) norms);
		glDrawArrays(GL_TRIANGLES,0, numVerts);
		

#else
	glVertexAttribPointer(v, 3, GL_FLOAT, GL_FALSE, 0,(const GLvoid*) verts);
        glVertexAttribPointer(n, 3, GL_FLOAT, GL_FALSE, 0,(const GLvoid*) norms);
        glVertexAttribPointer(t, 2, GL_FLOAT, GL_FALSE, 0,(const GLvoid*) texts);
        glEnableVertexAttribArray(v);
        glEnableVertexAttribArray(n);
        glEnableVertexAttribArray(t);
        
		glDrawArrays(GL_TRIANGLES, 0,numVerts);
    
#endif

	    
	}

};


void Tokenize(const string& str,
			  vector<string>& tokens,
			  const string& delimiters = " ")
{
	// Skip delimiters at beginning.
	string::size_type lastPos = str.find_first_not_of(delimiters, 0);
	// Find first "non-delimiter".
	string::size_type pos     = str.find_first_of(delimiters, lastPos);

	while (string::npos != pos || string::npos != lastPos)
	{
		// Found a token, add it to the vector.
		tokens.push_back(str.substr(lastPos, pos - lastPos));
		// Skip delimiters.  Note the "not_of"
		lastPos = str.find_first_not_of(delimiters, pos);
		// Find next "non-delimiter"
		pos = str.find_first_of(delimiters, lastPos);
	}
}

face* readFace(string fac1,string fac2,string fac3, vector<vec3*> verts, vector<vec2*> texts, vector<vec3*> norms){

	vector<string> vec;
	Tokenize(fac1,vec,"/");
	face *fac=new face();
	for(int i=0;i<(int)vec.size();i++){
		if(i==0){//v
			int ind=atoi(vec[i].c_str());
			fac->v1=ind-1;
		}
		if(i==1){//t
			if(!vec[i].empty()){
				int ind=atoi(vec[i].c_str());
				fac->t1=ind-1;
			}
		}
		if(i==2){//n
			int ind=atoi(vec[i].c_str());
			fac->n1=ind-1;
		}
	}

	vec.clear();
	Tokenize(fac2,vec,"/");
	for(int i=0;i<(int)vec.size();i++){
		if(i==0){//v
			int ind=atoi(vec[i].c_str());
			fac->v2=ind-1;
		}
		if(i==1){//t
			if(!vec[i].empty()){
				int ind=atoi(vec[i].c_str());
				fac->t2=ind-1;
			}
		}
		if(i==2){//n
			int ind=atoi(vec[i].c_str());
			fac->n2=ind-1;
		}
	}

	vec.clear();
	Tokenize(fac3,vec,"/");
	
	for(unsigned int i=0;i<vec.size();i++){
		if(i==0){//v
			int ind=atoi(vec[i].c_str());
			fac->v3=ind-1;
		}
		if(i==1){//t
			if(!vec[i].empty()){
				int ind=atoi(vec[i].c_str());
				fac->t3=ind-1;
			}
		}
		if(i==2){//n
			int ind=atoi(vec[i].c_str());
			fac->n3=ind-1;
		}

	}
	return fac;
}




obj3d * loadOBJ(const string file){
	string line;
	//LOG("comienza carga %s", file.c_str());
	ifstream myfile (file.c_str());
	if (myfile.is_open())
	{
		LOG("file open");
		vector<vec3*> verts,normals;
		vector<vec2*> texts;
		vector<face*> faces;
		while ( myfile.good() )
		{

			getline (myfile,line);
			//cout << line << endl;

			if(!line.empty() && line[0]!='#'){
				vector<string> spl;
				Tokenize(line,spl);
				string p1=spl[0];
				if(p1=="v"){
					float x=(float)atof(spl[1].c_str());
					float y=(float)atof(spl[2].c_str());
					float z=(float)atof(spl[3].c_str());
					vec3 *vert=new vec3(x,y,z);
					verts.push_back(vert);
				}
				else if(p1=="vt"){
					float x=(float)atof(spl[1].c_str());float y=(float)atof(spl[2].c_str());
					vec2 *vert=new vec2(x,y);
					texts.push_back(vert);
				}
				else if(p1=="vn"){
					float x=(float)atof(spl[1].c_str());float y=(float)atof(spl[2].c_str());float z=(float)atof(spl[3].c_str());
					vec3 *vert=new vec3(x,y,z);
					normals.push_back(vert);
				}
				else if(p1=="f"){
					face* fac=readFace(spl[1],spl[2],spl[3],verts,texts,normals);
					faces.push_back(fac);
				}

			}
		}



		myfile.close();
		obj3d* obj= new obj3d(faces,verts,texts, normals);
		//LOG("termina carga..");
		//LOG("%d", obj->numVerts);
		return obj;
	}

	return NULL; 

}




#endif 

